"""
商品缓存服务
使用Redis管理商品去重，避免重复推送
"""

import redis
import json
import hashlib
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Set
import logging

from app.config import settings

logger = logging.getLogger(__name__)


class ProductCacheService:
    """商品缓存服务"""
    
    def __init__(self):
        self.redis_client = redis.Redis.from_url(
            settings.REDIS_URL,
            decode_responses=True,
            socket_connect_timeout=5,
            socket_timeout=5
        )
        
        # 缓存配置
        self.USER_PRODUCT_TTL = 30 * 24 * 3600  # 用户级缓存30天
        self.GLOBAL_PRODUCT_TTL = 7 * 24 * 3600  # 全局缓存7天
        self.MONITOR_CACHE_TTL = 24 * 3600  # 监控缓存24小时
    
    def generate_product_key(self, product_data: Dict) -> str:
        """
        生成商品唯一标识
        基于商品的关键信息生成稳定的key
        """
        # 使用外部ID作为主要标识
        if external_id := product_data.get("external_id"):
            return external_id
        
        # 如果没有外部ID，基于标题+价格+卖家生成hash
        key_parts = [
            product_data.get("title", ""),
            str(product_data.get("price", "")),
            product_data.get("seller_id", ""),
            product_data.get("product_url", "")
        ]
        
        key_string = "|".join(key_parts)
        return hashlib.md5(key_string.encode()).hexdigest()
    
    def has_user_seen_product(self, user_id: int, product_key: str) -> bool:
        """检查用户是否已经看过这个商品"""
        cache_key = f"user_seen:{user_id}:{product_key}"
        return self.redis_client.exists(cache_key) > 0
    
    def mark_user_seen_product(self, user_id: int, product_key: str, product_data: Dict = None):
        """标记用户已看过商品"""
        cache_key = f"user_seen:{user_id}:{product_key}"
        
        # 存储基本信息用于调试
        cache_data = {
            "seen_at": datetime.now().isoformat(),
            "product_title": product_data.get("title", "") if product_data else "",
            "product_price": product_data.get("price", "") if product_data else ""
        }
        
        self.redis_client.setex(
            cache_key, 
            self.USER_PRODUCT_TTL, 
            json.dumps(cache_data)
        )
        
        logger.debug(f"标记用户 {user_id} 已看过商品 {product_key}")
    
    def has_global_seen_product(self, product_key: str) -> bool:
        """检查全局是否已经处理过这个商品"""
        cache_key = f"global_seen:{product_key}"
        return self.redis_client.exists(cache_key) > 0
    
    def mark_global_seen_product(self, product_key: str, product_data: Dict = None):
        """标记全局已处理商品"""
        cache_key = f"global_seen:{product_key}"
        
        cache_data = {
            "first_seen": datetime.now().isoformat(),
            "product_title": product_data.get("title", "") if product_data else ""
        }
        
        self.redis_client.setex(
            cache_key,
            self.GLOBAL_PRODUCT_TTL,
            json.dumps(cache_data)
        )
    
    def get_monitor_processed_count(self, monitor_id: int) -> int:
        """获取监控任务已处理商品数量"""
        cache_key = f"monitor_processed:{monitor_id}"
        count = self.redis_client.get(cache_key)
        return int(count) if count else 0
    
    def increment_monitor_processed(self, monitor_id: int) -> int:
        """增加监控任务处理计数"""
        cache_key = f"monitor_processed:{monitor_id}"
        count = self.redis_client.incr(cache_key)
        self.redis_client.expire(cache_key, self.MONITOR_CACHE_TTL)
        return count
    
    def get_user_daily_notifications(self, user_id: int) -> int:
        """获取用户今日通知数量"""
        today = datetime.now().strftime("%Y-%m-%d")
        cache_key = f"user_notifications:{user_id}:{today}"
        count = self.redis_client.get(cache_key)
        return int(count) if count else 0
    
    def increment_user_daily_notifications(self, user_id: int) -> int:
        """增加用户今日通知计数"""
        today = datetime.now().strftime("%Y-%m-%d")
        cache_key = f"user_notifications:{user_id}:{today}"
        count = self.redis_client.incr(cache_key)
        # 设置过期时间为明天凌晨
        tomorrow = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
        ttl = int((tomorrow - datetime.now()).total_seconds())
        self.redis_client.expire(cache_key, ttl)
        return count
    
    def batch_check_products(self, user_id: int, product_keys: List[str]) -> Dict[str, bool]:
        """批量检查商品是否已处理"""
        if not product_keys:
            return {}
        
        # 构建所有需要检查的key
        cache_keys = [f"user_seen:{user_id}:{key}" for key in product_keys]
        
        # 批量检查
        results = self.redis_client.mget(cache_keys)
        
        # 构建结果字典
        return {
            product_keys[i]: results[i] is not None 
            for i in range(len(product_keys))
        }
    
    def batch_mark_products(self, user_id: int, product_items: List[Dict]):
        """批量标记商品已处理"""
        if not product_items:
            return
        
        pipe = self.redis_client.pipeline()
        
        for item in product_items:
            product_key = item["product_key"]
            product_data = item.get("product_data", {})
            
            cache_key = f"user_seen:{user_id}:{product_key}"
            cache_data = {
                "seen_at": datetime.now().isoformat(),
                "product_title": product_data.get("title", ""),
                "product_price": product_data.get("price", "")
            }
            
            pipe.setex(cache_key, self.USER_PRODUCT_TTL, json.dumps(cache_data))
        
        pipe.execute()
        logger.debug(f"批量标记 {len(product_items)} 个商品已处理")
    
    def cleanup_expired_cache(self):
        """清理过期缓存（Redis会自动清理，这里主要用于统计）"""
        try:
            # 获取各类缓存的统计信息
            user_seen_keys = self.redis_client.keys("user_seen:*")
            global_seen_keys = self.redis_client.keys("global_seen:*")
            monitor_keys = self.redis_client.keys("monitor_processed:*")
            
            stats = {
                "user_seen_count": len(user_seen_keys),
                "global_seen_count": len(global_seen_keys),
                "monitor_cache_count": len(monitor_keys)
            }
            
            logger.info(f"缓存统计: {stats}")
            return stats
            
        except Exception as e:
            logger.error(f"清理缓存统计失败: {e}")
            return {}
    
    def get_cache_stats(self) -> Dict:
        """获取缓存统计信息"""
        try:
            info = self.redis_client.info()
            
            # 获取各类key的数量
            user_seen_count = len(self.redis_client.keys("user_seen:*"))
            global_seen_count = len(self.redis_client.keys("global_seen:*"))
            monitor_count = len(self.redis_client.keys("monitor_processed:*"))
            notification_count = len(self.redis_client.keys("user_notifications:*"))
            
            return {
                "redis_memory_used": info.get("used_memory_human", "unknown"),
                "redis_connected_clients": info.get("connected_clients", 0),
                "user_seen_products": user_seen_count,
                "global_seen_products": global_seen_count,
                "active_monitors": monitor_count,
                "daily_notifications": notification_count,
                "total_keys": info.get("db0", {}).get("keys", 0) if "db0" in info else 0
            }
            
        except Exception as e:
            logger.error(f"获取缓存统计失败: {e}")
            return {"error": str(e)}


# 创建全局实例
product_cache = ProductCacheService()
